#pragma once
#include <BWAPI.h>
#include <windows.h>

#include "DropShipManager.h"
#include "ZerglingBloodMacros.h"
#include "ZerglingController.h"
#include "ZBHeroManager.h"
#include "ZBAttackManager.h"

struct playerStats
{
	int zergling_count;
	int credit_count;
	int kill_count;
	int probe_count;
	int spawn_type;
	std::set<BWAPI::Unit *> heroes;
	/*Following values will be estimates for enemy players*/
	/*Position will be set to (0,0) if estimate is to be ignored*/
	//Estimates where the player's zerglings are currently spawning
	BWAPI::Position spawn_location;
	BWAPI::Position dropshipPos;
};

struct zerglingSquad
{
	int squadCount;
	int radius;
	BWAPI::Position target;
	std::set<BWAPI::Unit *> members;
	BWAPI::Unit* leader;
};

class ZerglingBlood : public BWAPI::AIModule
{
public:
	ZerglingBlood(){}
	virtual void onStart();
	virtual void onFrame();
	virtual void onSendText(std::string text);
	virtual void onReceiveText(BWAPI::Player* player, std::string text);
	virtual void onPlayerLeft(BWAPI::Player* player);
	virtual void onUnitDiscover(BWAPI::Unit* unit);
	virtual void onUnitEvade(BWAPI::Unit* unit);
	virtual void onUnitShow(BWAPI::Unit* unit);
	virtual void onUnitHide(BWAPI::Unit* unit);
	virtual void onUnitCreate(BWAPI::Unit* unit);
	virtual void onUnitDestroy(BWAPI::Unit* unit);
	void drawStats(); //not part of BWAPI::AIModule
	void drawBullets();
	void drawVisibilityData();
	void drawTerrainData();
	void showPlayers();
	void showForces();
	

	//Draws lines along the choke points of each base
	void drawChokes();

	//Prints unit position besides each non-zergling unit toggles all other
	//drawing information that is ontop of a unit off
	void drawUnitPos();

	//Prints unit type id besides each non-zergling unit toggles all other
	//drawing information that is ontop of a unit off
	void drawUnitID();

	//Draws the circles that Squads should stay in
	void drawSquadCircle();

private:
	/*Game state Variables*/
	bool show_bullets;
	bool show_visibility_data;
	bool show_chokes;
	bool show_unit_pos;
	bool show_unit_type_id;
	bool show_squad_circle;
	bool show_dship_pos;
	int spawn_location;
	int set_scouts;
	int squad_state;
	int attack_location;
	int game_state;

	BWAPI::Unit* fb;

	//BWAPI::Position move_target;

	void checkScouts();

	//Uptaded to the frame count every 25 frames ~= 1sec
	int frame_sec;
	
	/*
	Names are preceded by D,S, or B depending on the position for the drone
			[D]  S        [B]
	*When BWAITING drone will be at S
	XSPAWN		when drone changing to that type of zergling spawning
	XADJ		adjusting after the switch happens
	XWAITING	waiting while spawning at X
	*/
	enum game_state{STARTUP, PREMIDGAME, MIDGAME};
	enum spawn_state{SSPAWN, BSPAWN, DSPAWN, SADJ, BADJ, DADJ, SWAITING, BWAITING, DWAITING};
	enum base_command{BASE,SSHIP,DSHIP};
	enum attack_location{TOPLEFT, MIDDLELEFT, BOTTOMLEFT, TOPRIGHT, MIDDLERIGHT, BOTTOMRIGHT, MIDDLE, NONE};
	enum squad_state{MOVING, ATTACKING, WAITING, REGROUPING, RETREATING, SURROUNDING};
	void swapSpawn(int command);
	void checkSwap();

	void checkHealth();
	bool hasProbe(BWAPI::Color color);

	/*Returns base location as BWAPI::Position*/
    BWAPI::Position getBase(BWAPI::Player * player);

	/*Quick unit references*/
	std::set<BWAPI::Unit *> heroes;
	BWAPI::Unit* drone;
	BWAPI::Unit* dropShip;
	struct zerglingSquad squad;

	/*Player stats*/
	std::map< BWAPI::Color, struct playerStats> stats;
	void updateStats();
	void printStats();

	void groupMove(BWAPI::Position target);
	void groupAttack(BWAPI::Position target);
	void checkMove();
	void checkAttack();
	void startAttack(BWAPI::Position target);
	void surround(BWAPI::Position target, int radius);
	void checkSurround();

	BWAPI::Position my_target;
	int my_radius;

	/*Managers*/
	DropShipManager ship_manager;
	ZBAttackManager attack_manager;
	ZBHeroManager hero_manager;


	/*Utility Functions*/
	bool isGamePlayer(const BWAPI::Color & player_color)
	{
		return (player_color == COLOR_RED || player_color == COLOR_BLUE || player_color == COLOR_TEAL ||
		   player_color == COLOR_ORANGE || player_color == COLOR_BROWN || player_color == COLOR_PURPLE);
	}

	/*Ling Types*/
	//Should not have the same ling on different sets 
	std::set<BWAPI::Unit*> avaiLings;
	std::set<BWAPI::Unit*> recoLings;
	std::set<BWAPI::Unit*> scoutLings;
	std::set<BWAPI::Unit*> squadLings;
};
